<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    /*
    * 让异步操作 变成同步操作
    *   异步操作：定时器（每个定时器虽然时间不同，但是开启是同时开启的） 异步事件
    *
    * */

    setTimeout(function (){
        console.log("1")
    },1000)

    setTimeout(function (){
        console.log("2")
    },2000)

    //定时器执行，没有完全等待上一个定时器执行任务的完成才执行，就是同步事件执行完了，这两个异步事件的定时器同时开启，只不过一个是1秒之后自动执行，
    //另一个是2秒之后自动执行

    /*
    * 每天早上起来的流程
    * */
    function qichuang(cb){ //可以传一个函数，在这个函数操作完成之后执行回调函数
       setTimeout(function (){
           console.log("起床完成，可以下一步")
           cb()
       },1000)
    }

    function shuaya(){
        setTimeout(function (){
            console.log("刷牙完成，可以下一步")
        },3000)
    }

    function chizaofan(){
        setTimeout(function (){
            console.log("吃早饭完成，可以下一步")
        },2000)
    }

    function chumen(){
        setTimeout(function (){
            console.log("出门完成，可以下一步")
        },1500)
    }

    qichuang(shuaya) //起床内部传入刷牙，起床操作完成之后，才执行刷牙
    //但是如果这样的话，需要一个函数嵌套一个函数，多个函数嵌套会导致回调地狱问题:回调函数里面写回调函数...

    /*
    * promise 让异步代码在编写维护修改添加等操作的时候变得非常方便
    *
    *   可以将回调地狱扁平化 Promise构造函数 new方法 生成promise对象
    *
    * Promise 在实例化的时候接收一个回调函数作为参数，这个回调函数是所有异步操作的开端
    *    接收的回调函数中，可以接收两个参数：resolve reject（这两个参数都是函数）
    *       其中resolve表示异步操作成功
    *       reject则表示异步操作失败
    *
    * */

    /*
    * promise的语法特点：
    *   1.promise对象接收一个回调函数
    *   2.回调函数是第一段异步操作
    *   3.回调函数内部接收两个函数作为形参：resolve和reject
    *   4.resolve() 意味着紧挨着的下一个then执行
    *   5.then后续可以挨揍then 实现链式调用按顺序执行
    *   6.then里面的对象可以继续返回Promise对象 让下一个then执行
    *   7.如果promise对象这次执行成功，触发resolve，并且resolve(data)里面传了参数，则下一个执行的then就可以在形参拿到data
    *
    *
    * 链式操作
    * p
    *  .then()
    *  .then()
    *  .then()
    *  .then()
    *  .catch()
    *
    *
    * new Promise(function(resolve){
    *   resolve({})
    * })
    * .then(data => {
    *   console.log(data)
    * })
    *
    * */

    //promise通过.then .catch 等打点调用方式操作下一步，这种操作叫做链式操作
    let p = new Promise(function (resolve,reject){
        //写上一个异步操作
        setTimeout(function (){
            //异步操作1
            console.log("异步操作1执行完成")
            resolve() //操作执行成功
            //reject() //操作执行失败
        },1000)
    })

    //promise对象的 then操作 表示上一个函数操作执行完成并且resolve成功执行后，接下来做什么，即resolve是then的执行条件
    p.then(function (){

        //这里返回一个new生成的promise对象是因为接下来的then（异步操作3）不是延时定时器，是立马执行的，而当前这个then（异步操作2）是延时定时器，
        //异步操作会在同步操作执行之后，但是我们是想要在执行完异步操作2之后再执行下一个异步操作3，这时候就需要在这里生成一个新的promise对象，
        //在里面传入resolve和reject，这样下一个then（异步操作3）就会监听当前then（异步操作2）中的resolve是否执行成功，
        //从而使得异步操作3的then的执行顺序在异步操作2的then的执行顺序之后
        //所以只要出现异步操作，就需要再new生成一个promise对象
        return new Promise(function (resolve,reject){
            setTimeout(function (){
                console.log("异步操作2执行完成")
                resolve()
            },1000)
        })
    })

     //这里的then操作就会监听上一个then操作里面的执行结果是resolve还是reject，选择执行这里的then还是执行catch
     .then(() => {
         console.log("异步操作3执行完成")
     })

     //catch是监听上面所有操作，只要有一步是reject，就执行catch
     .catch(() => {
         console.log("执行失败")
     }) //如果上一步操作没有执行成功，触发了reject，则接下来执行catch操作，即reject是catch的执行条件



</script>
</body>
</html>